SlideShare a Scribd company logo
1 of 88
Download to read offline
Symfony 4
Workshop
Victoria Quirante - @vicqr
Nacho Martin - @nacmartin
Notes: http://symfony4.limenius.com/
Nacho Martín
@nacmartin
nacho@limenius.com
Victoria Quirante
@vicqr
victoria@limenius.com
We build tailor-made projects with Symfony and React
We have been working with Symfony since 2008
We provide development, consulting and training
Symfony 4
We are here
Symfony Evolution
Symfony 12005 A monolith (very different)
Symfony 22011 Components appear
Components used in popular projects
Doctrine
Silex
Laravel
Symfony Evolution
Symfony 12005 A monolith (very different)
Symfony 22011 Components appear
Symfony 32015 Brief intermediate step
Symfony 42017 Compose your apps
Symfony 2/3
SF 2
Web app
SF 2
API
SF 2
Microservice
SF 4
Web app
SF4
API
SF4
Microservice
Symfony 4
Symfony 4
SF4 SF 4
Web app
SF4
API
SF4
Microservice
We need something to smooth
out these transformations
Symfony Flex
Symfony Flex is a tool to implement
Symfony 4 philosophy
It is a composer plugin that comes with
Symfony 4
The idea is automation to the max
when installing and configuring packages
Modifies the behaviour of the
require and update commands
Allows Symfony to perform tasks before
or after the composer commands
Symfony 4
Your application
with Symfony Flex
composer req mailer
Symfony Flex
Server
Recipe?
No
Regular install
With composer
Symfony 4
Your application
with Symfony Flex
composer req mailer
Symfony Flex
Server
Recipe?
Yes
Install them
With composer
Follow recipe instructions
Decide which packages to install
Run any task to configure them
http://symfony.sh
Directory Structure
my-project/
├── config/
│   ├── bundles.php
│   ├── packages/
│   ├── routes.yaml
│   └── services.yaml
├── public/
│   └── index.php
├── src/
│   ├── ...
│   └── Kernel.php
├── templates/
└── vendor/
Doctrine
Entity
Entity
namespace AppEntity;
class Movie
{
private $id;
private $name;
private $director;
private $year;
private $picture;
}
Entity /**
* @ORMEntity()
* @ORMTable(name="movie")
*/
class Movie
{
/**
* @ORMColumn(type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORMColumn(type="string")
*/
private $name;
/**
* @ORMColumn(type="string", length=100)
*/
private $director;
/**
* @ORMColumn(type="smallint")
*/
private $year;
/**
* @ORMColumn(type="string")
*/
private $picture;
}
Entity
Code that has to do with the model itself.
Doesn’t depend on services, or query the DB.
Accessors
In this workshop we are going to use setters and getters:
•getDirector()
•setDirector()
This is not the only way. See for instance:
http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/
Entity Manager
Entity Manager
$em = $this->getDoctrine()->getManager();
$em->getRepository(Movie::class)->find($movieId);
$em = $this->getDoctrine()->getManager();
$em->persist($sale);
$em->flush();
Doctrine Query Language (DQL)
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT m, a FROM App:Movie m LEFT JOIN m.actors a WHERE
m.id = :id'
)->setParameter('id', $movieId);
$movie = $query->getOneOrNullResult();
Query Builder
$em = $this->getDoctrine()->getManager();
$query = $em->getRepository(Movie::class)
->createQueryBuilder('m')
->select('m, a')
->leftJoin('m.actors', 'a')
->where('m.id = :id')
->setParameter('id', $movieId)
->getQuery();
$movie = $query->getOneOrNullResult();
Entity Manager
Code that deals with retrieving or persisting
entities.
Fixtures

With Alice
We could do this
for ($i = 0; $i < 10; $i ++) {
$movie = new Movie();
$movie->setYear(1994);
$movie->setName('Pulp Fiction'.$i);
//...
$em->persist($movie);
}
$em->flush();
With Alice
AppEntityMovie:
movie{1..10}:
name: '<sentence(4, true)>'
director: '<name()>'
year: '<numberBetween(1970, 2017)>'
picture: '<image("./public/images", 500, 500, "cats", false)>'
See all the generators in
https://github.com/fzaninotto/Faker
Relationships
appentitymovie:
actor{1..10}:
#…
movie{1..10}:
#...
actors: ["@actor<numberBetween(1, 3)>", "@actor<numberBetween(4, 6)>"]
Twig
Twig
{{ }}
{% %}
Display Data
Define Structures
Access variables
{{ foo }}
{{ foo.bar }}
{{ foo['bar'] }}
- Checks if foo is an array and bar an element
- If not, checks if foo is an object and bar a property
- If not, checks if foo is an object and bar a method
- If not, checks if foo is an object and getBar a method
- If not, checks if foo is an object and isBar a method
{{ foo.bar }}
Access variables
{% for user in users %}
{{ user.username }}
{% endfor %}
For each
{% for i in 0..10 %}
{{ i }}
{% endfor %}
For
For … else
{% for item in items %}
{{ item }}
{% else %}
No items.
{% endfor %}
<html><head>...</head>
<body>
<h1>
{% block title %}{% endblock %}
</h1>
{% block body %}{% endblock %}
</body></html>
Template inheritance
templates/layout.html.twig
{% extends "layout.twig" %}
{% block title %}
Home
{% endblock %}
{% block body %}
Lorem ipsum...
{% endblock %}
Template inheritance
templates/home.html.twig
{% extends "layout.twig" %}
{% block title %}
Movie list
{% endblock %}
{% block body %}
Duis aute irure dolor in..
{% endblock %}
Template inheritance
templates/movies.html.twig
Webpack

Encore
Webpack
Webpack
The standard nowadays.
Very powerful.
Steep learning curve.
Cons
Pros
Webpack Encore
A wrapper around Webpack that makes it
easier to set up.
It solves a big % of cases.
If you require something specific, you can still
use Webpack without Encore.
Forms
Create a form
$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, ['label' => 'Create Post'])
->getForm();
return $this->render('default/new.html.twig', [
'form' => $form->createView(),
]);
Forms in Twig
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
You can customise a lot the rendering of every widget,
If you need to.
Handle submission
$form = $this->createFormBuilder($task)
->add('task', TextType::class)
->add('dueDate', DateType::class)
->add('save', SubmitType::class, ['label' => 'Create Task'])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($task);
$em->flush();
return $this->redirectToRoute('task_success');
}
return $this->render('default/new.html.twig', [
'form' => $form->createView(),
]);
Forms in their own classes
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task')
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Task::class,
));
}
}
Events
Event and EventListener
Event EventListener
dispatch
Event
class SaleEvent extends Event
{
const NAME = 'sale.created';
protected $sale;
protected $movie;
protected $numTickets;
public function __construct(Sale $sale, Movie $movie, int $numTickets)
{
$this->sale = $sale;
$this->movie = $movie;
$this->numTickets = $numTickets;
}
public function getSale()
{
return $this->sale;
}
public function getMovie()
{
return $this->movie;
}
public function getNumTickets()
{
return $this->numTickets;
}
}
A bag of parameters
that describe the event
Dispatch Events
$this->get('event_dispatcher')
->dispatch(
SaleEvent::NAME,
new SaleEvent($sale, $movie, $numTickets)
);
EventListener
Processes the event
class SaleListener
{
public function __construct(EntityManager $em)
{
$this->em = $em;
}
public function onSaleCreated(SaleEvent $event)
{
for ($i = 0; $i < $event->getNumTickets(); $i++) {
$ticket = new Ticket();
$ticket->setMovie($event->getMovie());
$ticket->setSale($event->getSale());
$ticket->setRow(1);
$ticket->setSeat(1);
$this->em->persist($ticket);
}
}
}
Services
Services
A service is an object that does something:
• Generate a thumbnail.
• Generate a PDF.
• A query to ElasticSearch.
• Log something.
• Send an email.
Example
class SaleLogger
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function log(Sale $sale)
{
$this->logger->info('Sold ' . count($sale->getTickets()) . ' tickets to ' . $sale->getFullName());
}
}
Where does this come from?
Using services
public function listAction(SaleLogger $saleLogger)
{
//…
$saleLogger->log($sale);
}
Is injected with dependencies
Explicit configuration
# app/config/services.yml
services:
# explicitly configure the service
AppLoggerSaleLogger:
arguments:
$logger: '@monolog.logger.request'
Tagged services
$taggedServices = $container->findTaggedServiceIds(‘app.my_tag’);
foreach ($taggedServices as $id => $tags) {
$definition->addMethodCall('callAMethod', array(new Reference($id)));
}
AppMyServices:
resource: '../src/MyServices'
tags: ['app.my_tag']
Validation
Built in assertions
/**
* @ORMColumn(type="string")
* @AssertLength(min=2)
*/
private $fullName;
/**
* @ORMColumn(type="string")
* @AssertEmail()
*/
private $email;
/**
* @ORMColumn(type="text")
* @AssertLength(max=100)
*/
private $question;
Built in assertions
There are 47 assertions
From NotNull to Isbn
And we can write our
own assertions
Use validators
if ($form->isValid()) {}
$author = new Author();
$validator = $this->get('validator');
$errors = $validator->validate($author);
Dependency container
Standalone use
$email = ‘obama@usa.gov’;
$emailConstraint = new AssertEmail();
$emailConstraint->message = 'Invalid email address';
$errorList = $this->get('validator')->validate(
$email,
$emailConstraint
);
Creating new constraints
Constraint Validator
Validate
Constraint
class HasAvailableSeats extends Constraint
{
public $message = 'No {{ number }} available seats’;
protected $movie;
public function __construct($options)
{
$this->movie = $options['movie'];
}
public function getMovie()
{
return $this->movie;
}
public function validatedBy()
{
return get_class($this).'Validator';
}
}
No logic,
data that describes
the constraint
Who validates this?
class HasAvailableSeatsValidator extends ConstraintValidator
{
public function validate($value, Constraint $constraint)
{
$available = $constraint->getMovie()->getAvailableSeats();
if ($value > $available) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ number }}', $value)
->addViolation();
}
}
}
Validator
Validation logic
APIs
Up to level 2
Good use of HTTP verbs (GET, POST, PUT, DELETE, PATCH…)
Structure based on resources (/movies, /movies/31).
Use of HTTP Status codes (200, 201, 406, …).
Use of representations (JSON, XML, …).
Serializer: the idea
$recipe = new Recipe();
$recipe->setName($content['name']);
$recipe->setEnergy($content['energy']);
$recipe->setServings($content['servings']);
Request->Our object (manual deserialization)
$responseData = [
   'id' => $recipe->getId(),
   'name' => $recipe->getName(),
   'energy' => $recipe->getEnergy(),
   'servings' => $recipe->getServings(),
   ];
$response = new JsonResponse($responseData, 201);
Our object->Request (manual serialization)
Tedious!
$response = new Response($serializer->serialize($recipe, 'json'), 201);
$responseData = [
   'id' => $recipe->getId(),
   'name' => $recipe->getName(),
   'energy' => $recipe->getEnergy(),
   'servings' => $recipe->getServings(),
   ];
$response = new JsonResponse($responseData, 201);
Our object->Request (manual serialization)
Serialize
$recipe = $serializer->deserialize($content, Recipe::class, 'json');
$recipe = new Recipe();
$recipe->setName($content['name']);
$recipe->setEnergy($content['energy']);
$recipe->setServings($content['servings']);
Request->Our object (manual deserialization)
Deserialize
Serializer
Representation in API != DB
{
id: 9,
name: "victoriaq",
password: "encryptedPassword",
email: "victoria@limenius.com",
avatar: "avatar.jpg",
twitter_handler: "vicqr",
profile: {
id: 19,
bio: "My bio."
}
}
I want this to be “username”
I don’t want to expose it!
Only in profile, not in list
We want to prepend “thumb_”
Only in version 2 of the API
I’d like this to be bio:”My bio”
We do this in the normalizer
Annotations
MaxDepth
• Detect and limit the serialization depth
• Especially useful when serializing large trees
Groups
• Sometimes, you want to serialize different sets of attributes from your entities
• Groups are a handy way to achieve this need
API Platform makes it very easy
Admin Panel
Admin on REST with API Platform
Sonata Admin
Easy Admin
Thanks! @nacmartin
nacho@limenius.com
@vicqr
victoria@limenius.com

More Related Content

What's hot

Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Stephan Hochdörfer
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming Enguest9bcef2f
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)James Titcumb
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)James Titcumb
 
Being Dangerous with Twig
Being Dangerous with TwigBeing Dangerous with Twig
Being Dangerous with TwigRyan Weaver
 
Testing API platform with Behat BDD tests
Testing API platform with Behat BDD testsTesting API platform with Behat BDD tests
Testing API platform with Behat BDD testsStefan Adolf
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)James Titcumb
 
Getting big without getting fat, in perl
Getting big without getting fat, in perlGetting big without getting fat, in perl
Getting big without getting fat, in perlDean Hamstead
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)James Titcumb
 
Solving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteSolving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteIsaacSchlueter
 
TWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHPTWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHPCesare D'Amico
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkJeremy Kendall
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceJesse Vincent
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with PerlDave Cross
 
CSS in React - Will Change Transform
CSS in React - Will Change TransformCSS in React - Will Change Transform
CSS in React - Will Change TransformJoe Seifi
 

What's hot (19)

Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13Your Business. Your Language. Your Code - dpc13
Your Business. Your Language. Your Code - dpc13
 
Non Conventional Android Programming En
Non Conventional Android Programming EnNon Conventional Android Programming En
Non Conventional Android Programming En
 
A Phing fairy tale - ConFoo13
A Phing fairy tale - ConFoo13A Phing fairy tale - ConFoo13
A Phing fairy tale - ConFoo13
 
Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)Crafting Quality PHP Applications (ConFoo YVR 2017)
Crafting Quality PHP Applications (ConFoo YVR 2017)
 
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
Kicking off with Zend Expressive and Doctrine ORM (ConFoo YVR 2017)
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
 
Being Dangerous with Twig
Being Dangerous with TwigBeing Dangerous with Twig
Being Dangerous with Twig
 
Actions filters
Actions filtersActions filters
Actions filters
 
Testing API platform with Behat BDD tests
Testing API platform with Behat BDD testsTesting API platform with Behat BDD tests
Testing API platform with Behat BDD tests
 
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
Dip Your Toes in the Sea of Security (ConFoo YVR 2017)
 
Getting big without getting fat, in perl
Getting big without getting fat, in perlGetting big without getting fat, in perl
Getting big without getting fat, in perl
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
Solving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoCompleteSolving Real World Problems with YUI 3: AutoComplete
Solving Real World Problems with YUI 3: AutoComplete
 
TWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHPTWIG: the flexible, fast and secure template language for PHP
TWIG: the flexible, fast and secure template language for PHP
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret SauceBeijing Perl Workshop 2008 Hiveminder Secret Sauce
Beijing Perl Workshop 2008 Hiveminder Secret Sauce
 
Modern Web Development with Perl
Modern Web Development with PerlModern Web Development with Perl
Modern Web Development with Perl
 
CSS in React - Will Change Transform
CSS in React - Will Change TransformCSS in React - Will Change Transform
CSS in React - Will Change Transform
 

Similar to Symfony 4 Workshop - Limenius

The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010Fabien Potencier
 
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with MagentoMeet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with MagentoKristof Ringleff
 
Things to consider for testable Code
Things to consider for testable CodeThings to consider for testable Code
Things to consider for testable CodeFrank Kleine
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War StoriesJakub Zalas
 
Refactoring Simple Example
Refactoring Simple ExampleRefactoring Simple Example
Refactoring Simple Exampleliufabin 66688
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...Fwdays
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarYonni Mendes
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suckRoss Bruniges
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)Javier Eguiluz
 
Javascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & AngularJavascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & AngularErik Guzman
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricksJavier Eguiluz
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)Oleg Zinchenko
 

Similar to Symfony 4 Workshop - Limenius (20)

The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with MagentoMeet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
Meet Magento DE 2016 - Kristof Ringleff - Growing up with Magento
 
Things to consider for testable Code
Things to consider for testable CodeThings to consider for testable Code
Things to consider for testable Code
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 
Refactoring Simple Example
Refactoring Simple ExampleRefactoring Simple Example
Refactoring Simple Example
 
Growing up with Magento
Growing up with MagentoGrowing up with Magento
Growing up with Magento
 
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac..."Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
"Full Stack frameworks or a story about how to reconcile Front (good) and Bac...
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Zend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinarZend server 6 using zf2, 2013 webinar
Zend server 6 using zf2, 2013 webinar
 
Writing JavaScript that doesn't suck
Writing JavaScript that doesn't suckWriting JavaScript that doesn't suck
Writing JavaScript that doesn't suck
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Event Sourcing with php
Event Sourcing with phpEvent Sourcing with php
Event Sourcing with php
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Javascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & AngularJavascript Memory leaks and Performance & Angular
Javascript Memory leaks and Performance & Angular
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)DDD on example of Symfony (Webcamp Odessa 2014)
DDD on example of Symfony (Webcamp Odessa 2014)
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 

More from Ignacio Martín

Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native WorkshopIgnacio Martín
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and SymfonyIgnacio Martín
 
Server Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPServer Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPIgnacio Martín
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server SideIgnacio Martín
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React AlicanteIgnacio Martín
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React AlicanteIgnacio Martín
 
Asegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTAsegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTIgnacio Martín
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Ignacio Martín
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projectsIgnacio Martín
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Ignacio Martín
 
Adding Realtime to your Projects
Adding Realtime to your ProjectsAdding Realtime to your Projects
Adding Realtime to your ProjectsIgnacio Martín
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsIgnacio Martín
 

More from Ignacio Martín (17)

Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native Workshop
 
Server side rendering with React and Symfony
Server side rendering with React and SymfonyServer side rendering with React and Symfony
Server side rendering with React and Symfony
 
Server Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHPServer Side Rendering of JavaScript in PHP
Server Side Rendering of JavaScript in PHP
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server Side
 
Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
React Native Workshop - React Alicante
React Native Workshop - React AlicanteReact Native Workshop - React Alicante
React Native Workshop - React Alicante
 
Asegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWTAsegurando APIs en Symfony con JWT
Asegurando APIs en Symfony con JWT
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
Integrating React.js with PHP projects
Integrating React.js with PHP projectsIntegrating React.js with PHP projects
Integrating React.js with PHP projects
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
Keeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
 
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)Integrando React.js en aplicaciones Symfony (deSymfony 2016)
Integrando React.js en aplicaciones Symfony (deSymfony 2016)
 
Adding Realtime to your Projects
Adding Realtime to your ProjectsAdding Realtime to your Projects
Adding Realtime to your Projects
 
Symfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worldsSymfony & Javascript. Combining the best of two worlds
Symfony & Javascript. Combining the best of two worlds
 
Symfony 2 CMF
Symfony 2 CMFSymfony 2 CMF
Symfony 2 CMF
 
Doctrine2 sf2Vigo
Doctrine2 sf2VigoDoctrine2 sf2Vigo
Doctrine2 sf2Vigo
 
Presentacion git
Presentacion gitPresentacion git
Presentacion git
 

Recently uploaded

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Intelisync
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfkalichargn70th171
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyFrank van der Linden
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 

Recently uploaded (20)

Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)Introduction to Decentralized Applications (dApps)
Introduction to Decentralized Applications (dApps)
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Engage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The UglyEngage Usergroup 2024 - The Good The Bad_The Ugly
Engage Usergroup 2024 - The Good The Bad_The Ugly
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 

Symfony 4 Workshop - Limenius

  • 1. Symfony 4 Workshop Victoria Quirante - @vicqr Nacho Martin - @nacmartin Notes: http://symfony4.limenius.com/
  • 2. Nacho Martín @nacmartin nacho@limenius.com Victoria Quirante @vicqr victoria@limenius.com We build tailor-made projects with Symfony and React We have been working with Symfony since 2008 We provide development, consulting and training
  • 5. Symfony Evolution Symfony 12005 A monolith (very different) Symfony 22011 Components appear
  • 6. Components used in popular projects
  • 10. Symfony Evolution Symfony 12005 A monolith (very different) Symfony 22011 Components appear Symfony 32015 Brief intermediate step Symfony 42017 Compose your apps
  • 11. Symfony 2/3 SF 2 Web app SF 2 API SF 2 Microservice SF 4 Web app SF4 API SF4 Microservice Symfony 4
  • 12. Symfony 4 SF4 SF 4 Web app SF4 API SF4 Microservice We need something to smooth out these transformations
  • 14. Symfony Flex is a tool to implement Symfony 4 philosophy
  • 15. It is a composer plugin that comes with Symfony 4 The idea is automation to the max when installing and configuring packages
  • 16. Modifies the behaviour of the require and update commands Allows Symfony to perform tasks before or after the composer commands
  • 17. Symfony 4 Your application with Symfony Flex composer req mailer Symfony Flex Server Recipe? No Regular install With composer
  • 18. Symfony 4 Your application with Symfony Flex composer req mailer Symfony Flex Server Recipe? Yes Install them With composer Follow recipe instructions Decide which packages to install Run any task to configure them
  • 20. Directory Structure my-project/ ├── config/ │   ├── bundles.php │   ├── packages/ │   ├── routes.yaml │   └── services.yaml ├── public/ │   └── index.php ├── src/ │   ├── ... │   └── Kernel.php ├── templates/ └── vendor/
  • 23. Entity namespace AppEntity; class Movie { private $id; private $name; private $director; private $year; private $picture; }
  • 24. Entity /** * @ORMEntity() * @ORMTable(name="movie") */ class Movie { /** * @ORMColumn(type="integer") * @ORMId * @ORMGeneratedValue(strategy="AUTO") */ private $id; /** * @ORMColumn(type="string") */ private $name; /** * @ORMColumn(type="string", length=100) */ private $director; /** * @ORMColumn(type="smallint") */ private $year; /** * @ORMColumn(type="string") */ private $picture; }
  • 25. Entity Code that has to do with the model itself. Doesn’t depend on services, or query the DB.
  • 26. Accessors In this workshop we are going to use setters and getters: •getDirector() •setDirector() This is not the only way. See for instance: http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/
  • 28. Entity Manager $em = $this->getDoctrine()->getManager(); $em->getRepository(Movie::class)->find($movieId); $em = $this->getDoctrine()->getManager(); $em->persist($sale); $em->flush();
  • 29. Doctrine Query Language (DQL) $em = $this->getDoctrine()->getManager(); $query = $em->createQuery( 'SELECT m, a FROM App:Movie m LEFT JOIN m.actors a WHERE m.id = :id' )->setParameter('id', $movieId); $movie = $query->getOneOrNullResult();
  • 30. Query Builder $em = $this->getDoctrine()->getManager(); $query = $em->getRepository(Movie::class) ->createQueryBuilder('m') ->select('m, a') ->leftJoin('m.actors', 'a') ->where('m.id = :id') ->setParameter('id', $movieId) ->getQuery(); $movie = $query->getOneOrNullResult();
  • 31. Entity Manager Code that deals with retrieving or persisting entities.
  • 33. We could do this for ($i = 0; $i < 10; $i ++) { $movie = new Movie(); $movie->setYear(1994); $movie->setName('Pulp Fiction'.$i); //... $em->persist($movie); } $em->flush();
  • 34. With Alice AppEntityMovie: movie{1..10}: name: '<sentence(4, true)>' director: '<name()>' year: '<numberBetween(1970, 2017)>' picture: '<image("./public/images", 500, 500, "cats", false)>' See all the generators in https://github.com/fzaninotto/Faker
  • 36. Twig
  • 37. Twig {{ }} {% %} Display Data Define Structures
  • 38. Access variables {{ foo }} {{ foo.bar }} {{ foo['bar'] }}
  • 39. - Checks if foo is an array and bar an element - If not, checks if foo is an object and bar a property - If not, checks if foo is an object and bar a method - If not, checks if foo is an object and getBar a method - If not, checks if foo is an object and isBar a method {{ foo.bar }} Access variables
  • 40. {% for user in users %} {{ user.username }} {% endfor %} For each
  • 41. {% for i in 0..10 %} {{ i }} {% endfor %} For
  • 42. For … else {% for item in items %} {{ item }} {% else %} No items. {% endfor %}
  • 43. <html><head>...</head> <body> <h1> {% block title %}{% endblock %} </h1> {% block body %}{% endblock %} </body></html> Template inheritance templates/layout.html.twig
  • 44. {% extends "layout.twig" %} {% block title %} Home {% endblock %} {% block body %} Lorem ipsum... {% endblock %} Template inheritance templates/home.html.twig
  • 45. {% extends "layout.twig" %} {% block title %} Movie list {% endblock %} {% block body %} Duis aute irure dolor in.. {% endblock %} Template inheritance templates/movies.html.twig
  • 48. Webpack The standard nowadays. Very powerful. Steep learning curve. Cons Pros
  • 49. Webpack Encore A wrapper around Webpack that makes it easier to set up. It solves a big % of cases. If you require something specific, you can still use Webpack without Encore.
  • 50. Forms
  • 51. Create a form $form = $this->createFormBuilder($task) ->add('task', TextType::class) ->add('dueDate', DateType::class) ->add('save', SubmitType::class, ['label' => 'Create Post']) ->getForm(); return $this->render('default/new.html.twig', [ 'form' => $form->createView(), ]);
  • 52. Forms in Twig {{ form_start(form) }} {{ form_widget(form) }} {{ form_end(form) }} You can customise a lot the rendering of every widget, If you need to.
  • 53. Handle submission $form = $this->createFormBuilder($task) ->add('task', TextType::class) ->add('dueDate', DateType::class) ->add('save', SubmitType::class, ['label' => 'Create Task']) ->getForm(); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $em = $this->getDoctrine()->getManager(); $em->persist($task); $em->flush(); return $this->redirectToRoute('task_success'); } return $this->render('default/new.html.twig', [ 'form' => $form->createView(), ]);
  • 54. Forms in their own classes class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('task') ->add('dueDate', null, array('widget' => 'single_text')) ->add('save', SubmitType::class); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => Task::class, )); } }
  • 56. Event and EventListener Event EventListener dispatch
  • 57. Event class SaleEvent extends Event { const NAME = 'sale.created'; protected $sale; protected $movie; protected $numTickets; public function __construct(Sale $sale, Movie $movie, int $numTickets) { $this->sale = $sale; $this->movie = $movie; $this->numTickets = $numTickets; } public function getSale() { return $this->sale; } public function getMovie() { return $this->movie; } public function getNumTickets() { return $this->numTickets; } } A bag of parameters that describe the event
  • 59. EventListener Processes the event class SaleListener { public function __construct(EntityManager $em) { $this->em = $em; } public function onSaleCreated(SaleEvent $event) { for ($i = 0; $i < $event->getNumTickets(); $i++) { $ticket = new Ticket(); $ticket->setMovie($event->getMovie()); $ticket->setSale($event->getSale()); $ticket->setRow(1); $ticket->setSeat(1); $this->em->persist($ticket); } } }
  • 61. Services A service is an object that does something: • Generate a thumbnail. • Generate a PDF. • A query to ElasticSearch. • Log something. • Send an email.
  • 62. Example class SaleLogger { private $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } public function log(Sale $sale) { $this->logger->info('Sold ' . count($sale->getTickets()) . ' tickets to ' . $sale->getFullName()); } } Where does this come from?
  • 63. Using services public function listAction(SaleLogger $saleLogger) { //… $saleLogger->log($sale); } Is injected with dependencies
  • 64. Explicit configuration # app/config/services.yml services: # explicitly configure the service AppLoggerSaleLogger: arguments: $logger: '@monolog.logger.request'
  • 65. Tagged services $taggedServices = $container->findTaggedServiceIds(‘app.my_tag’); foreach ($taggedServices as $id => $tags) { $definition->addMethodCall('callAMethod', array(new Reference($id))); } AppMyServices: resource: '../src/MyServices' tags: ['app.my_tag']
  • 67. Built in assertions /** * @ORMColumn(type="string") * @AssertLength(min=2) */ private $fullName; /** * @ORMColumn(type="string") * @AssertEmail() */ private $email; /** * @ORMColumn(type="text") * @AssertLength(max=100) */ private $question;
  • 68. Built in assertions There are 47 assertions From NotNull to Isbn And we can write our own assertions
  • 69. Use validators if ($form->isValid()) {} $author = new Author(); $validator = $this->get('validator'); $errors = $validator->validate($author); Dependency container
  • 70. Standalone use $email = ‘obama@usa.gov’; $emailConstraint = new AssertEmail(); $emailConstraint->message = 'Invalid email address'; $errorList = $this->get('validator')->validate( $email, $emailConstraint );
  • 72. Constraint class HasAvailableSeats extends Constraint { public $message = 'No {{ number }} available seats’; protected $movie; public function __construct($options) { $this->movie = $options['movie']; } public function getMovie() { return $this->movie; } public function validatedBy() { return get_class($this).'Validator'; } } No logic, data that describes the constraint Who validates this?
  • 73. class HasAvailableSeatsValidator extends ConstraintValidator { public function validate($value, Constraint $constraint) { $available = $constraint->getMovie()->getAvailableSeats(); if ($value > $available) { $this->context->buildViolation($constraint->message) ->setParameter('{{ number }}', $value) ->addViolation(); } } } Validator Validation logic
  • 74. APIs
  • 75.
  • 76. Up to level 2 Good use of HTTP verbs (GET, POST, PUT, DELETE, PATCH…) Structure based on resources (/movies, /movies/31). Use of HTTP Status codes (200, 201, 406, …). Use of representations (JSON, XML, …).
  • 77. Serializer: the idea $recipe = new Recipe(); $recipe->setName($content['name']); $recipe->setEnergy($content['energy']); $recipe->setServings($content['servings']); Request->Our object (manual deserialization) $responseData = [    'id' => $recipe->getId(),    'name' => $recipe->getName(),    'energy' => $recipe->getEnergy(),    'servings' => $recipe->getServings(),    ]; $response = new JsonResponse($responseData, 201); Our object->Request (manual serialization) Tedious!
  • 78. $response = new Response($serializer->serialize($recipe, 'json'), 201); $responseData = [    'id' => $recipe->getId(),    'name' => $recipe->getName(),    'energy' => $recipe->getEnergy(),    'servings' => $recipe->getServings(),    ]; $response = new JsonResponse($responseData, 201); Our object->Request (manual serialization) Serialize
  • 79. $recipe = $serializer->deserialize($content, Recipe::class, 'json'); $recipe = new Recipe(); $recipe->setName($content['name']); $recipe->setEnergy($content['energy']); $recipe->setServings($content['servings']); Request->Our object (manual deserialization) Deserialize
  • 81. Representation in API != DB { id: 9, name: "victoriaq", password: "encryptedPassword", email: "victoria@limenius.com", avatar: "avatar.jpg", twitter_handler: "vicqr", profile: { id: 19, bio: "My bio." } } I want this to be “username” I don’t want to expose it! Only in profile, not in list We want to prepend “thumb_” Only in version 2 of the API I’d like this to be bio:”My bio” We do this in the normalizer
  • 82. Annotations MaxDepth • Detect and limit the serialization depth • Especially useful when serializing large trees Groups • Sometimes, you want to serialize different sets of attributes from your entities • Groups are a handy way to achieve this need
  • 83. API Platform makes it very easy
  • 85. Admin on REST with API Platform